package login

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"regexp"
	"strings"
	"time"

	"oschina.net/justin.qin/baidu_sign/common"

	"github.com/bitly/go-simplejson"
)

//GetLoginStatus 检测是否需要通过密码登录，即cookie是否过期。true：不需要；false：需要
func GetLoginStatus(ptrCookieJar *cookiejar.Jar) bool {
	body, err := common.Fetch("common.Fetch//tieba.baidu.com/dc/common/tbs", nil, ptrCookieJar)
	if err != nil {
		return false
	}
	json, parseErr := simplejson.NewJson([]byte(body))
	if parseErr != nil {
		return false
	}
	return json.Get("is_login").MustInt() == 1
}

func BaiduLogin(username, password string, ptrCookieJar *cookiejar.Jar, path string) (result int, err error) {
	loginToken, tokenError := GetLoginToken(ptrCookieJar)
	if tokenError != nil {
		return 0, tokenError
	}
	return BaiduLoginWithCaptcha(username, password, ptrCookieJar, "", "", loginToken, path)
}

func GetLoginToken(ptrCookieJar *cookiejar.Jar) (string, error) {
	GetBaiduID(ptrCookieJar)
	body, FetchErr := common.Fetch("https://passport.baidu.com/v2/api/?getapi&tpl=tb&apiver=v3&tt="+GetTimestampStr()+"520&class=login&logintype=dialogLogin", nil, ptrCookieJar)
	if FetchErr != nil {
		return "", FetchErr
	}
	body = strings.Replace(body, "'", "\"", -1)
	json, parseErr := simplejson.NewJson([]byte(body))
	if parseErr != nil {
		return "", parseErr
	}
	token, accessError := json.Get("data").Get("token").String()
	if accessError != nil {
		return "", accessError
	}
	return token, nil
}

func BaiduLoginWithCaptcha(username, password string, ptrCookieJar *cookiejar.Jar, codeString, verifyCode, loginToken, path string) (result int, err error) {
	postData := make(map[string]string)
	postData["apiver"] = "v3"
	postData["charset"] = "UTF-8"
	postData["codestring"] = codeString
	postData["isPhone"] = "false"
	postData["logintype"] = "bascilogin"
	postData["mem_pass"] = "on"
	postData["password"] = password
	postData["ppui_logintime"] = "8888"
	postData["quick_user"] = "0"
	postData["safeflg"] = "0"
	postData["splogin"] = "rate"
	postData["staticpage"] = "http://tieba.baidu.com/tb/static-common/html/pass/v3Jump.html"
	postData["token"] = loginToken
	postData["tpl"] = "tb"
	postData["tt"] = GetTimestampStr() + "520"
	postData["u"] = "http://tieba.baidu.com/"
	postData["username"] = username
	postData["verifycode"] = verifyCode

	body, FetchErr := common.Fetch("https://passport.baidu.com/v2/api/?login", postData, ptrCookieJar)
	if FetchErr != nil {
		return 0, FetchErr
	}

	errNo := regexp.MustCompile("err_no=(\\d+)").FindString(body)
	if errNo == "err_no=400031" {
		fmt.Println("Login-protect was on, please turn it off as passport.baidu.com")
		return -1, nil // 登陆保护
	}
	if errNo == "err_no=4" {
		fmt.Println("Wrong username or password")
		return -2, nil // 用户名 / 密码有误
	}
	if matched, _ := regexp.Match("captchaservice", []byte(body)); matched {
		reg, _ := regexp.Compile("(captchaservice\\w{200,})")
		fmt.Println("Server denied logging request and sent a captcha.")
		codeString = reg.FindString(body)
		fmt.Println("Please open captcha image manually: captcha.jpg")
		verifyImage, _ := common.Fetch("https://passport.baidu.com/cgi-bin/genimage?"+codeString, nil, ptrCookieJar)
		ioutil.WriteFile(path+"/captcha.jpg", []byte(verifyImage), 0644)
		fmt.Print("Now enter the captcha: ")
		fmt.Scan(&verifyCode)
		return BaiduLoginWithCaptcha(username, password, ptrCookieJar, codeString, verifyCode, loginToken, path)
	}
	if errNo != "" && errNo != "err_no=0" {
		fmt.Println("Unknown error. Error number:", errNo)
		return -3, nil
	}

	return 1, nil
}

func GetBaiduID(ptrCookieJar *cookiejar.Jar) string {
	baiduID := getBaiduID(ptrCookieJar)
	if baiduID == "" {
		common.Fetch("https://passport.baidu.com/v2/", nil, ptrCookieJar)
		baiduID = getBaiduID(ptrCookieJar)
	}
	return baiduID
}

func getBaiduID(ptrCookieJar *cookiejar.Jar) string {
	return GetCookie(ptrCookieJar, "BAIDUID")
}

func GetTimestampStr() string {
	return fmt.Sprintf("%d", time.Now().Unix())
}

func GetCookie(cookieJar *cookiejar.Jar, name string) string {
	cookieUrl, _ := url.Parse("http://tieba.baidu.com")
	cookies := cookieJar.Cookies(cookieUrl)
	for _, cookie := range cookies {
		if name == cookie.Name {
			return cookie.Value
		}
	}
	return ""
}

func GetCookies(cookieJar *cookiejar.Jar) []*http.Cookie {
	cookieUrl, _ := url.Parse("http://tieba.baidu.com")
	cookies := cookieJar.Cookies(cookieUrl)
	return cookies
}
